/*
 *
 */

package socket;

import io.AsyncServerByteSocket;
import io.AsyncServerSocket;
import io.AsyncServerByteSocketEventListener;
import io.SocketChannelWrapper;
import io.stripframe.FrameProcessor;
import io.stripframe.FrameStripper;
import io.stripframe.HeaderTailStripper;
import io.stripframe.RawlStripper;

import java.nio.channels.SocketChannel;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;

import core.IEC104Server;
import core.ProcessThread;

import protocol.Command;
import protocol.iec104.IEC104Commandexception;
import protocol.iec104.IEC104Command;
import util.DataUtil;


/**
 *
 */
public class FunccodeServerEventListener extends ProcServerEventListener implements AsyncServerByteSocketEventListener {
	private static Logger logger = Logger.getLogger(FunccodeServerEventListener.class);
	private static char frameHeader = (char)2;
	private static char frameTail = (char)3;
	private Map channelFrameStripperMap;
	private final AsyncServerByteSocket server;
	private class ProcServerFrameProcessor implements FrameProcessor {
		private final SocketChannel channel;
		private final String ipAddr;
		public ProcServerFrameProcessor(SocketChannel channel) {
			this.channel = channel;
			ipAddr = channel.socket().getInetAddress().getHostAddress();
		}
		public void process(String s) {
			System.out.print("process: "+ s);
			ProcessThread thd = IEC104Server.getProcThread(ipAddr);
			if (thd != null) {
				try {
					Command command = new IEC104Command(s); //构造消息报文
					thd.feedCommand(command); //add to queue
				} catch (IEC104Commandexception e) {
					logger.error("frame "+s+" error", e);				
				} catch (Throwable e) {
					logger.error("runtime error", e);
				}
			}
		}
	}
	public FunccodeServerEventListener(AsyncServerByteSocket server) {
		this.server = server;
		channelFrameStripperMap = new HashMap();			
	}
	
	public void onClose(SocketChannel channel) {
		logger.info(channel.socket().getRemoteSocketAddress()+" disconnected");
		channelFrameStripperMap.remove(channel);
	}

	
	public void onClientRead(SocketChannel channel, String s) {
		logger.info("read from "+channel.socket().getRemoteSocketAddress()+" -- "+s);
		FrameStripper stripper = (FrameStripper)channelFrameStripperMap.get(channel);
		if (stripper != null) {
			stripper.putString(s);					
		}
	}
	
	
	public void onAccept(SocketChannel channel) {
		logger.info(channel.socket().getRemoteSocketAddress()+" connected");	
		FrameStripper stripper= new RawlStripper();
		//FrameStripper stripper = new HeaderTailStripper(frameHeader, frameTail);
		stripper.attachObserver(new ProcServerFrameProcessor(channel));	
		ProcessThread thd = IEC104Server.getProcThread(channel.socket().getInetAddress().getHostAddress());
		if (thd != null) {
			SocketChannelWrapper oldChannel = thd.getCommClient();	
			if (oldChannel != null) {
				this.server.closeClient(oldChannel.getChannel());
			}	
			thd.setCommClient(new SocketChannelWrapper(channel));
			
		}
		channelFrameStripperMap.put(channel, stripper);
	}

	@Override
	public void onClientRead(SocketChannel channel, byte[] bts) {
		// TODO Auto-generated method stub
		String s= DataUtil.BytesToHexStr(bts);
		logger.info("read from "+channel.socket().getRemoteSocketAddress()+" -- "+s);
		FrameStripper stripper = (FrameStripper)channelFrameStripperMap.get(channel);
		
		if (stripper != null) {
			stripper.putString(s);					
		}
		
	}
}